package com.centaline.web.aop;

import com.aist.uam.auth.remote.UamSessionService;
import com.aist.uam.auth.remote.vo.SessionUser;
import com.alibaba.fastjson.JSONObject;
import com.centaline.core.SystemServiceLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;


/**
 * Created by caoyuan7 on 2017/9/22.
 * 提供日志记录的打印
 */
@Aspect
@Component
public class SystemLogAspect {

    @Autowired(required = true)
    UamSessionService uamSessionService;

    /**
     * 日志记录
     */
    private final static Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

    /**
     * Service层切点
     */
    @Pointcut("@annotation(com.centaline.core.SystemServiceLog)")
    public void serviceAspect() {}

    /**
     * execution(* com.centaline..*.controller..*(..)) ||
     */
    @Pointcut("execution(* com.centaline.apply..*.service.impl..*(..))")
    public void methodPointcut(){}

    /**
     * doServiceLog:获取注解参数，记录日志. <br/>
     * @author caoy
     * @param joinPoint 切入点参数
     */
    @After("serviceAspect()")
    public void doServiceLog(JoinPoint joinPoint) throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //获取管理员用户信息
        SessionUser admin = uamSessionService.getSessionUser();
        //获取日志描述信息
        String content = getServiceMthodDescription(joinPoint);
        //获取参数信息
        String parameter = getServiceMthodParams(joinPoint);
        //获取方法名称
        String methodName = joinPoint.getSignature().getName();

        logger.info("logs record:"+admin.getRealName() + "，handle：" + content+"，method name："+methodName+"，parameter:"+parameter);

    }
    @After("methodPointcut()")
    public void doControllerLog(JoinPoint joinPoint) throws Exception {
        //获取管理员用户信息
        SessionUser admin = uamSessionService.getSessionUser();
        //获取方法名称
        String methodName = joinPoint.getSignature().getName();
        //获取参数信息
        String parameter = getServiceMthodParams(joinPoint);
        //logger.info("Controller日志记录:" + admin.getUsername() + "的操作，方法名：" + methodName + "，参数信息:" +parameter);
        logger.info("logs record:" + admin.getUsername() + "，handle，method name：" + methodName + "，parameter:" +parameter);
    }

    /**
     * getServiceMthodDescription:获取注解中对方法的描述信息 用于service层注解
     * @author caoy
     * @param joinPoint 切点
     * @return 方法描述
     * @throws Exception
     */
    private String getServiceMthodDescription(JoinPoint joinPoint)
            throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String description = "";
        for(Method method : methods) {
            if(method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if(clazzs.length == arguments.length) {
                    description = method.getAnnotation(SystemServiceLog.class).description();
                    break;
                }
            }
        }
        return description;
    }

    /**
     * getServiceMthodTableType:获取注解中对方法的数据表类型 用于service层注解 . <br/>
     * @author caoy
     * @param joinPoint
     * @return tableType
     * @throws Exception
     */
    private int getServiceMthodTableType(JoinPoint joinPoint)
            throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        int tableType = 0;
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    tableType = method.getAnnotation(SystemServiceLog.class).tableType();
                    break;
                }
            }
        }
        return tableType;
    }

    /**
     * getServiceMthodParams:获取json格式的参数. <br/>
     * @author caoy
     * @param joinPoint
     * @return params
     * @throws Exception
     */
    private String getServiceMthodParams(JoinPoint joinPoint)
            throws Exception {
        Object[] arguments = joinPoint.getArgs();
        String params = JSONObject.toJSONString(arguments);
        return params;
    }

}